﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WindowsFormsApplication1;

namespace debugger
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        public Form1 mainForm;

        private void Form2_Load(object sender, EventArgs e)
        {
        }

        private void spiCSOn()
        {
            mainForm.portWriteNew((byte)(0x70), 1);

        }
        private void spiCSOff()
        {
            mainForm.portWriteNew((byte)(0x70), 0);

        }

        private uint spiRec()
        {
            mainForm.portWriteNew((byte)(0x72), 0);
            uint temp = mainForm.readFromPort();
            return temp;
        }

        private void spiSend(int val)
        {
            mainForm.portWriteNew((byte)(0x71), (byte)val);

            {
                mainForm.portWriteNew((byte)(0x73), 0);
                uint temp = mainForm.readFromPort();
                if (temp != 123)
                {
                    throw new Exception("checkerror");
                }
            }
        }

        int WaitUntilReady()
        {
            int cnt = 0;
            while (true)
            {
                spiCSOn();
                spiSend(0x05);

                uint val = spiRec();
                spiCSOff();

                if ((val & 1) == 0) { break; }

                cnt++;
            }
            return cnt;
        }
        private uint readByte(int addr)
        {
            spiCSOn();
            //spiSend(0x03);
            spiSend(0x0B);

            spiSend((addr >> 16) & 0x0FF);
            spiSend((addr >> 8) & 0x0FF);
            spiSend((addr >> 0) & 0x0FF);

            spiSend(0x00);

            uint val = spiRec();

            spiCSOff();

            return val;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();

            spiCSOn();
            spiSend(0x9F);
            textBox1.Text = spiRec() + "," + spiRec() + "," + spiRec();
            spiCSOff();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();
            byte[] data = readSector(int.Parse(this.textBox2.Text));

            int err = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 4096; i++)
            {
                if ((i & 15) == 0)
                {
                    sb.Append("\r\n");
                }
                sb.Append(Util.getHex2(data[i]));
                sb.Append(" ");
            }

            textBox1.Text = err + ",\r\n" + sb.ToString();

        }

        private void button3_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();
            int totalM = int.Parse(this.textBox3.Text);

            byte[] buff = new byte[totalM * 1024 * 1024];

            FileStream fs = new FileStream("rom.bin", FileMode.Open, FileAccess.Read);
            fs.Read(buff, 0, totalM * 1024 * 1024);
            fs.Close();

            for (int i = 0; i < totalM * 256; i++)//1Mbyte = 256 sec
            {
                while (true)
                {
                    try
                    {
                        bool isSame = false;
                        byte[] data;
                        //byte[] data = readSectorMem(i);
                        //for (int j = 0; j < 4096; j++)
                        //{
                        //    if (buff[i * 4096 + j] != data[j])
                        //    {
                        //        isSame = false;
                        //        break;
                        //    }
                        //}
                        if (!isSame)
                        {
                            Console.WriteLine("write sec:" + i);
                            writeSector(i, buff, i * 4096);//4k / sec
                        }
                        data = readSector(i);
                        bool err = false;
                        for (int j = 0; j < 4096; j++)
                        {
                            if (buff[i * 4096 + j] != data[j])
                            {
                                err = true;
                                break;
                            }
                        }
                        if (!err)
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                    mainForm.clearBuff();
                    this.Text = "err";
                    spiCSOn();
                    spiCSOff();
                }
                this.Text = i + "/" + (totalM * 256);
            }
            textBox1.Text = "ok";
        }

        private void button4_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();

            spiCSOn();
            spiSend(0x05);
            textBox1.Text = "" + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x35);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

        }

        private void button5_Click(object sender, EventArgs e)
        {
            //读otherpage
            mainForm.clearBuff();

            spiCSOn();
            spiSend(0x06);//we
            spiCSOff();

        }

        private void button6_Click(object sender, EventArgs e)
        {
            //读otherpage
            mainForm.clearBuff();

            spiCSOn();
            spiSend(0x04);//we off
            spiCSOff();

        }

        private void button7_Click(object sender, EventArgs e)
        {
            //mainForm.clearBuff();
            //byte[] buff = new byte[57344 * 4];
            //
            //FileStream fs = new FileStream("e:\\Bom Bom (Radio Edit) 2.wav", FileMode.Open, FileAccess.Read);
            //fs.Seek(int.Parse(""), SeekOrigin.Begin);
            //fs.Read(buff, 0, 57344 * 4);
            //fs.Close();
            //
            ////mainForm.clearBuff();
            //for (int i = 0; i < 57344; i++)
            //{
            //    double v = i;
            //    v = v / int.Parse("");
            //    v = Math.Sin(v);
            //    v = v + 1;
            //    v = v * 128;
            //
            //    uint val = buff[i * 4];
            //    val += buff[i * 4 + 1];
            //    val += buff[i * 4 + 2];
            //    val += buff[i * 4 + 3];
            //    val = val / 4;
            //    mainForm.setmem((uint)i, val, true);
            //    if ((i & 1023) == 0) this.Text = i + "";
            //}
        }

        private void writeSector(int sec, byte[] data, int offset)
        {
            int addr = sec * 4096;

            spiCSOn();
            spiSend(0x06);//we
            spiCSOff();

            spiCSOn();
            spiSend(0x20);//se
            spiSend((addr >> 16) & 0x0FF);
            spiSend((addr >> 8) & 0x0FF);
            spiSend((addr >> 0) & 0x0FF);
            spiCSOff();

            int cnt = WaitUntilReady();


            for (int page = 0; page < 16; page++)
            {


                spiCSOn();
                spiSend(0x06);//we
                spiCSOff();

                spiCSOn();
                addr = sec * 4096 + page * 256;
                spiSend(0x02);//pp
                spiSend((addr >> 16) & 0x0FF);
                spiSend((addr >> 8) & 0x0FF);
                spiSend((addr >> 0) & 0x0FF);

                for (int i = 0; i < 256; i++)
                {
                    spiSend(data[offset + page * 256 + i]);
                }

                spiCSOff();

                cnt = WaitUntilReady();
            }

        }

        private byte[] readSectorMem(int sec)
        {
            byte[] data = new byte[4096];
            int addr = sec * 4096;
            for (int i = 0; i < 4096; i += 4)
            {
                uint val1 = mainForm.getmem((uint)(0x40000000 + sec * 4096 + i), null);
                uint val2 = mainForm.getmem((uint)(0x40000000 + sec * 4096 + i), null);
                if (val1 == val2)
                {
                    data[i] = (byte)(val1 & 0xFF);
                    data[i + 1] = (byte)((val1 >> 8) & 0xFF);
                    data[i + 2] = (byte)((val1 >> 16) & 0xFF);
                    data[i + 3] = (byte)((val1 >> 24) & 0xFF);
                }
                else {
                    throw new Exception("val1 != val2");
                }
            }
            return data;
        }

        private byte[] readSector(int sec)
        {
            byte[] data = new byte[4096];
            int addr = sec * 4096;
            spiCSOn();
            //spiSend(0x03);
            spiSend(0x0B);
            spiSend((addr >> 16) & 0x0FF);
            spiSend((addr >> 8) & 0x0FF);
            spiSend((addr >> 0) & 0x0FF);
            spiSend(0x00);
            for (int i = 0; i < 4096; i++)
            {
                data[i] = (byte)spiRec();
            }
            spiCSOff();
            return data;
        }

        uint[] char_table = {
0x00000000,0x00000000,0x00000000,0x00000000, 
0x00007E81,0xA58181BD,0x9981817E,0x00000000, 
0x00007EFF,0xDBFFFFC3,0xE7FFFF7E,0x00000000, 
0x00000000,0x6CFEFEFE,0xFE7C3810,0x00000000, 
0x00000000,0x10387CFE,0x7C381000,0x00000000, 
0x00000018,0x3C3CE7E7,0xE718183C,0x00000000, 
0x00000018,0x3C7EFFFF,0x7E18183C,0x00000000, 
0x00000000,0x0000183C,0x3C180000,0x00000000, 
0xFFFFFFFF,0xFFFFE7C3,0xC3E7FFFF,0xFFFFFFFF, 
0x00000000,0x003C6642,0x42663C00,0x00000000, 
0xFFFFFFFF,0xFFC399BD,0xBD99C3FF,0xFFFFFFFF, 
0x00001E0E,0x1A3278CC,0xCCCCCC78,0x00000000, 
0x00003C66,0x6666663C,0x187E1818,0x00000000, 
0x00003F33,0x3F303030,0x3070F0E0,0x00000000, 
0x00007F63,0x7F636363,0x6367E7E6,0xC0000000, 
0x00000018,0x18DB3CE7,0x3CDB1818,0x00000000, 
0x0080C0E0,0xF0F8FEF8,0xF0E0C080,0x00000000, 
0x0002060E,0x1E3EFE3E,0x1E0E0602,0x00000000, 
0x0000183C,0x7E181818,0x7E3C1800,0x00000000, 
0x00006666,0x66666666,0x66006666,0x00000000, 
0x00007FDB,0xDBDB7B1B,0x1B1B1B1B,0x00000000, 
0x007CC660,0x386CC6C6,0x6C380CC6,0x7C000000, 
0x00000000,0x00000000,0xFEFEFEFE,0x00000000, 
0x0000183C,0x7E181818,0x7E3C187E,0x00000000, 
0x0000183C,0x7E181818,0x18181818,0x00000000, 
0x00001818,0x18181818,0x187E3C18,0x00000000, 
0x00000000,0x00180CFE,0x0C180000,0x00000000, 
0x00000000,0x003060FE,0x60300000,0x00000000, 
0x00000000,0x0000C0C0,0xC0FE0000,0x00000000, 
0x00000000,0x00286CFE,0x6C280000,0x00000000, 
0x00000000,0x1038387C,0x7CFEFE00,0x00000000, 
0x00000000,0xFEFE7C7C,0x38381000,0x00000000, 
0x00000000,0x00000000,0x00000000,0x00000000, 
0x0000183C,0x3C3C1818,0x18001818,0x00000000, 
0x00666666,0x24000000,0x00000000,0x00000000, 
0x0000006C,0x6CFE6C6C,0x6CFE6C6C,0x00000000, 
0x18187CC6,0xC2C07C06,0x0686C67C,0x18180000, 
0x00000000,0xC2C60C18,0x3060C686,0x00000000, 
0x0000386C,0x6C3876DC,0xCCCCCC76,0x00000000, 
0x00303030,0x60000000,0x00000000,0x00000000, 
0x00000C18,0x30303030,0x3030180C,0x00000000, 
0x00003018,0x0C0C0C0C,0x0C0C1830,0x00000000, 
0x00000000,0x00663CFF,0x3C660000,0x00000000, 
0x00000000,0x0018187E,0x18180000,0x00000000, 
0x00000000,0x00000000,0x00181818,0x30000000, 
0x00000000,0x000000FE,0x00000000,0x00000000, 
0x00000000,0x00000000,0x00001818,0x00000000, 
0x00000000,0x02060C18,0x3060C080,0x00000000, 
0x0000386C,0xC6C6D6D6,0xC6C66C38,0x00000000, 
0x00001838,0x78181818,0x1818187E,0x00000000, 
0x00007CC6,0x060C1830,0x60C0C6FE,0x00000000, 
0x00007CC6,0x06063C06,0x0606C67C,0x00000000, 
0x00000C1C,0x3C6CCCFE,0x0C0C0C1E,0x00000000, 
0x0000FEC0,0xC0C0FC06,0x0606C67C,0x00000000, 
0x00003860,0xC0C0FCC6,0xC6C6C67C,0x00000000, 
0x0000FEC6,0x06060C18,0x30303030,0x00000000, 
0x00007CC6,0xC6C67CC6,0xC6C6C67C,0x00000000, 
0x00007CC6,0xC6C67E06,0x06060C78,0x00000000, 
0x00000000,0x18180000,0x00181800,0x00000000, 
0x00000000,0x18180000,0x00181830,0x00000000, 
0x00000006,0x0C183060,0x30180C06,0x00000000, 
0x00000000,0x007E0000,0x7E000000,0x00000000, 
0x00000060,0x30180C06,0x0C183060,0x00000000, 
0x00007CC6,0xC60C1818,0x18001818,0x00000000, 
0x0000007C,0xC6C6DEDE,0xDEDCC07C,0x00000000, 
0x00001038,0x6CC6C6FE,0xC6C6C6C6,0x00000000, 
0x0000FC66,0x66667C66,0x666666FC,0x00000000, 
0x00003C66,0xC2C0C0C0,0xC0C2663C,0x00000000, 
0x0000F86C,0x66666666,0x66666CF8,0x00000000, 
0x0000FE66,0x62687868,0x606266FE,0x00000000, 
0x0000FE66,0x62687868,0x606060F0,0x00000000, 
0x00003C66,0xC2C0C0DE,0xC6C6663A,0x00000000, 
0x0000C6C6,0xC6C6FEC6,0xC6C6C6C6,0x00000000, 
0x00003C18,0x18181818,0x1818183C,0x00000000, 
0x00001E0C,0x0C0C0C0C,0xCCCCCC78,0x00000000, 
0x0000E666,0x666C7878,0x6C6666E6,0x00000000, 
0x0000F060,0x60606060,0x606266FE,0x00000000, 
0x0000C6EE,0xFEFED6C6,0xC6C6C6C6,0x00000000, 
0x0000C6E6,0xF6FEDECE,0xC6C6C6C6,0x00000000, 
0x00007CC6,0xC6C6C6C6,0xC6C6C67C,0x00000000, 
0x0000FC66,0x66667C60,0x606060F0,0x00000000, 
0x00007CC6,0xC6C6C6C6,0xC6D6DE7C,0x0C0E0000, 
0x0000FC66,0x66667C6C,0x666666E6,0x00000000, 
0x00007CC6,0xC660380C,0x06C6C67C,0x00000000, 
0x00007E7E,0x5A181818,0x1818183C,0x00000000, 
0x0000C6C6,0xC6C6C6C6,0xC6C6C67C,0x00000000, 
0x0000C6C6,0xC6C6C6C6,0xC66C3810,0x00000000, 
0x0000C6C6,0xC6C6D6D6,0xD6FEEE6C,0x00000000, 
0x0000C6C6,0x6C7C3838,0x7C6CC6C6,0x00000000, 
0x00006666,0x66663C18,0x1818183C,0x00000000, 
0x0000FEC6,0x860C1830,0x60C2C6FE,0x00000000, 
0x00003C30,0x30303030,0x3030303C,0x00000000, 
0x00000080,0xC0E07038,0x1C0E0602,0x00000000, 
0x00003C0C,0x0C0C0C0C,0x0C0C0C3C,0x00000000, 
0x10386CC6,0x00000000,0x00000000,0x00000000, 
0x00000000,0x00000000,0x00000000,0x00FF0000, 
0x30301800,0x00000000,0x00000000,0x00000000, 
0x00000000,0x00780C7C,0xCCCCCC76,0x00000000, 
0x0000E060,0x60786C66,0x6666667C,0x00000000, 
0x00000000,0x007CC6C0,0xC0C0C67C,0x00000000, 
0x00001C0C,0x0C3C6CCC,0xCCCCCC76,0x00000000, 
0x00000000,0x007CC6FE,0xC0C0C67C,0x00000000, 
0x0000386C,0x6460F060,0x606060F0,0x00000000, 
0x00000000,0x0076CCCC,0xCCCCCC7C,0x0CCC7800, 
0x0000E060,0x606C7666,0x666666E6,0x00000000, 
0x00001818,0x00381818,0x1818183C,0x00000000, 
0x00000606,0x000E0606,0x06060606,0x66663C00, 
0x0000E060,0x60666C78,0x786C66E6,0x00000000, 
0x00003818,0x18181818,0x1818183C,0x00000000, 
0x00000000,0x00ECFED6,0xD6D6D6C6,0x00000000, 
0x00000000,0x00DC6666,0x66666666,0x00000000, 
0x00000000,0x007CC6C6,0xC6C6C67C,0x00000000, 
0x00000000,0x00DC6666,0x6666667C,0x6060F000, 
0x00000000,0x0076CCCC,0xCCCCCC7C,0x0C0C1E00, 
0x00000000,0x00DC7666,0x606060F0,0x00000000, 
0x00000000,0x007CC660,0x380CC67C,0x00000000, 
0x00001030,0x30FC3030,0x3030361C,0x00000000, 
0x00000000,0x00CCCCCC,0xCCCCCC76,0x00000000, 
0x00000000,0x00666666,0x66663C18,0x00000000, 
0x00000000,0x00C6C6D6,0xD6D6FE6C,0x00000000, 
0x00000000,0x00C66C38,0x38386CC6,0x00000000, 
0x00000000,0x00C6C6C6,0xC6C6C67E,0x060CF800, 
0x00000000,0x00FECC18,0x3060C6FE,0x00000000, 
0x00000E18,0x18187018,0x1818180E,0x00000000, 
0x00001818,0x18180018,0x18181818,0x00000000, 
0x00007018,0x18180E18,0x18181870,0x00000000, 
0x000076DC,0x00000000,0x00000000,0x00000000, 
0x00000000,0x10386CC6,0xC6C6FE00,0x00000000, 
0x00003C66,0xC2C0C0C0,0xC2663C0C,0x067C0000, 
0x0000CC00,0x00CCCCCC,0xCCCCCC76,0x00000000, 
0x000C1830,0x007CC6FE,0xC0C0C67C,0x00000000, 
0x0010386C,0x00780C7C,0xCCCCCC76,0x00000000, 
0x0000CC00,0x00780C7C,0xCCCCCC76,0x00000000, 
0x00603018,0x00780C7C,0xCCCCCC76,0x00000000, 
0x00386C38,0x00780C7C,0xCCCCCC76,0x00000000, 
0x00000000,0x3C666060,0x663C0C06,0x3C000000, 
0x0010386C,0x007CC6FE,0xC0C0C67C,0x00000000, 
0x0000C600,0x007CC6FE,0xC0C0C67C,0x00000000, 
0x00603018,0x007CC6FE,0xC0C0C67C,0x00000000, 
0x00006600,0x00381818,0x1818183C,0x00000000, 
0x00183C66,0x00381818,0x1818183C,0x00000000, 
0x00603018,0x00381818,0x1818183C,0x00000000, 
0x00C60010,0x386CC6C6,0xFEC6C6C6,0x00000000, 
0x386C3800,0x386CC6C6,0xFEC6C6C6,0x00000000, 
0x18306000,0xFE66607C,0x606066FE,0x00000000, 
0x00000000,0x00CC7636,0x7ED8D86E,0x00000000, 
0x00003E6C,0xCCCCFECC,0xCCCCCCCE,0x00000000, 
0x0010386C,0x007CC6C6,0xC6C6C67C,0x00000000, 
0x0000C600,0x007CC6C6,0xC6C6C67C,0x00000000, 
0x00603018,0x007CC6C6,0xC6C6C67C,0x00000000, 
0x003078CC,0x00CCCCCC,0xCCCCCC76,0x00000000, 
0x00603018,0x00CCCCCC,0xCCCCCC76,0x00000000, 
0x0000C600,0x00C6C6C6,0xC6C6C67E,0x060C7800, 
0x00C6007C,0xC6C6C6C6,0xC6C6C67C,0x00000000, 
0x00C600C6,0xC6C6C6C6,0xC6C6C67C,0x00000000, 
0x0018183C,0x66606060,0x663C1818,0x00000000, 
0x00386C64,0x60F06060,0x6060E6FC,0x00000000, 
0x00006666,0x3C187E18,0x7E181818,0x00000000, 
0x00F8CCCC,0xF8C4CCDE,0xCCCCCCC6,0x00000000, 
0x000E1B18,0x18187E18,0x18181818,0xD8700000, 
0x00183060,0x00780C7C,0xCCCCCC76,0x00000000, 
0x000C1830,0x00381818,0x1818183C,0x00000000, 
0x00183060,0x007CC6C6,0xC6C6C67C,0x00000000, 
0x00183060,0x00CCCCCC,0xCCCCCC76,0x00000000, 
0x000076DC,0x00DC6666,0x66666666,0x00000000, 
0x76DC00C6,0xE6F6FEDE,0xCEC6C6C6,0x00000000, 
0x003C6C6C,0x3E007E00,0x00000000,0x00000000, 
0x00386C6C,0x38007C00,0x00000000,0x00000000, 
0x00003030,0x00303060,0xC0C6C67C,0x00000000, 
0x00000000,0x0000FEC0,0xC0C0C000,0x00000000, 
0x00000000,0x0000FE06,0x06060600,0x00000000, 
0x00C0C0C2,0xC6CC1830,0x60DC860C,0x183E0000, 
0x00C0C0C2,0xC6CC1830,0x66CE9E3E,0x06060000, 
0x00001818,0x00181818,0x3C3C3C18,0x00000000, 
0x00000000,0x00366CD8,0x6C360000,0x00000000, 
0x00000000,0x00D86C36,0x6CD80000,0x00000000, 
0x11441144,0x11441144,0x11441144,0x11441144, 
0x55AA55AA,0x55AA55AA,0x55AA55AA,0x55AA55AA, 
0xDD77DD77,0xDD77DD77,0xDD77DD77,0xDD77DD77, 
0x18181818,0x18181818,0x18181818,0x18181818, 
0x18181818,0x181818F8,0x18181818,0x18181818, 
0x18181818,0x18F818F8,0x18181818,0x18181818, 
0x36363636,0x363636F6,0x36363636,0x36363636, 
0x00000000,0x000000FE,0x36363636,0x36363636, 
0x00000000,0x00F818F8,0x18181818,0x18181818, 
0x36363636,0x36F606F6,0x36363636,0x36363636, 
0x36363636,0x36363636,0x36363636,0x36363636, 
0x00000000,0x00FE06F6,0x36363636,0x36363636, 
0x36363636,0x36F606FE,0x00000000,0x00000000, 
0x36363636,0x363636FE,0x00000000,0x00000000, 
0x18181818,0x18F818F8,0x00000000,0x00000000, 
0x00000000,0x000000F8,0x18181818,0x18181818, 
0x18181818,0x1818181F,0x00000000,0x00000000, 
0x18181818,0x181818FF,0x00000000,0x00000000, 
0x00000000,0x000000FF,0x18181818,0x18181818, 
0x18181818,0x1818181F,0x18181818,0x18181818, 
0x00000000,0x000000FF,0x00000000,0x00000000, 
0x18181818,0x181818FF,0x18181818,0x18181818, 
0x18181818,0x181F181F,0x18181818,0x18181818, 
0x36363636,0x36363637,0x36363636,0x36363636, 
0x36363636,0x3637303F,0x00000000,0x00000000, 
0x00000000,0x003F3037,0x36363636,0x36363636, 
0x36363636,0x36F700FF,0x00000000,0x00000000, 
0x00000000,0x00FF00F7,0x36363636,0x36363636, 
0x36363636,0x36373037,0x36363636,0x36363636, 
0x00000000,0x00FF00FF,0x00000000,0x00000000, 
0x36363636,0x36F700F7,0x36363636,0x36363636, 
0x18181818,0x18FF00FF,0x00000000,0x00000000, 
0x36363636,0x363636FF,0x00000000,0x00000000, 
0x00000000,0x00FF00FF,0x18181818,0x18181818, 
0x00000000,0x000000FF,0x36363636,0x36363636, 
0x36363636,0x3636363F,0x00000000,0x00000000, 
0x18181818,0x181F181F,0x00000000,0x00000000, 
0x00000000,0x001F181F,0x18181818,0x18181818, 
0x00000000,0x0000003F,0x36363636,0x36363636, 
0x36363636,0x363636FF,0x36363636,0x36363636, 
0x18181818,0x18FF18FF,0x18181818,0x18181818, 
0x18181818,0x181818F8,0x00000000,0x00000000, 
0x00000000,0x0000001F,0x18181818,0x18181818, 
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, 
0x00000000,0x000000FF,0xFFFFFFFF,0xFFFFFFFF, 
0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0, 
0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F, 
0xFFFFFFFF,0xFFFFFF00,0x00000000,0x00000000, 
0x00000000,0x0076DCD8,0xD8D8DC76,0x00000000, 
0x000078CC,0xCCCCD8CC,0xC6C6C6CC,0x00000000, 
0x0000FEC6,0xC6C0C0C0,0xC0C0C0C0,0x00000000, 
0x00000000,0xFE6C6C6C,0x6C6C6C6C,0x00000000, 
0x000000FE,0xC6603018,0x3060C6FE,0x00000000, 
0x00000000,0x007ED8D8,0xD8D8D870,0x00000000, 
0x00000000,0x66666666,0x667C6060,0xC0000000, 
0x00000000,0x76DC1818,0x18181818,0x00000000, 
0x0000007E,0x183C6666,0x663C187E,0x00000000, 
0x00000038,0x6CC6C6FE,0xC6C66C38,0x00000000, 
0x0000386C,0xC6C6C66C,0x6C6C6CEE,0x00000000, 
0x00001E30,0x180C3E66,0x6666663C,0x00000000, 
0x00000000,0x007EDBDB,0xDB7E0000,0x00000000, 
0x00000003,0x067EDBDB,0xF37E60C0,0x00000000, 
0x00001C30,0x60607C60,0x6060301C,0x00000000, 
0x0000007C,0xC6C6C6C6,0xC6C6C6C6,0x00000000, 
0x00000000,0xFE0000FE,0x0000FE00,0x00000000, 
0x00000000,0x18187E18,0x180000FF,0x00000000, 
0x00000030,0x180C060C,0x1830007E,0x00000000, 
0x0000000C,0x18306030,0x180C007E,0x00000000, 
0x00000E1B,0x1B181818,0x18181818,0x18181818, 
0x18181818,0x18181818,0xD8D8D870,0x00000000, 
0x00000000,0x1818007E,0x00181800,0x00000000, 
0x00000000,0x0076DC00,0x76DC0000,0x00000000, 
0x00386C6C,0x38000000,0x00000000,0x00000000, 
0x00000000,0x00000018,0x18000000,0x00000000, 
0x00000000,0x00000000,0x18000000,0x00000000, 
0x000F0C0C,0x0C0C0CEC,0x6C6C3C1C,0x00000000, 
0x00D86C6C,0x6C6C6C00,0x00000000,0x00000000, 
0x0070D830,0x60C8F800,0x00000000,0x00000000, 
0x00000000,0x7C7C7C7C,0x7C7C7C00,0x00000000, 
0x00000000,0x00000000,0x00000000,0x00000000
};

        private void button10_Click(object sender, EventArgs e)
        {
            byte[] data = new byte[1024 * 1024];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = 0xFF;
            }
            //bios.bin
            {
                FileStream fs = new FileStream("bios.bin", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0, (int)fs.Length);
                fs.Close();
            }
            //char_table 0x40000 256k
            for (int i = 0; i < char_table.Length; i++)
            {
                data[0x40000 + i * 4 + 0] = (byte)((char_table[i] >> 0) & 0xFF);
                data[0x40000 + i * 4 + 1] = (byte)((char_table[i] >> 8) & 0xFF);
                data[0x40000 + i * 4 + 2] = (byte)((char_table[i] >> 16) & 0xFF);
                data[0x40000 + i * 4 + 3] = (byte)((char_table[i] >> 24) & 0xFF);
            }

            //cursor    0x50000 256K+64K
            //{
            //    FileStream fs = new FileStream("bios.bin", FileMode.Open, FileAccess.Read);
            //    fs.Read(data, 0x50000, (int)fs.Length);
            //    fs.Close();
            //}

            //HZK16  0x80000 512k
            {
                FileStream fs = new FileStream("HZK16", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0x80000, (int)fs.Length);
                fs.Close();
            }

            {
                FileStream fs = new FileStream("rom.bin", FileMode.Create, FileAccess.Write);
                fs.Write(data, 0, 1024 * 1024);
                fs.Close();
            }
            MessageBox.Show("rom.bin ok");
        }

        private void button8_Click(object sender, EventArgs e)
        {
            int totalM = int.Parse(this.textBox3.Text);

            byte[] data = new byte[totalM * 1024 * 1024];
            
            
            Random r = new Random();
            r.NextBytes(data);
            //for (uint i = 0; i < data.Length; i+=4) {
            //    byte byte0 = 0x00;
            //    byte byte1 = 0x40;
            //    byte byte2 = 0x80;
            //    byte byte3 = 0xC0;
            //
            //    uint v0 = i & 0x3F;
            //    uint v1 = (i>>6) & 0x3F;
            //    uint v2 = (i >> 12) & 0x3F;
            //    uint v3 = (i>>18) & 0x3F;
            //
            //    data[i + 0] = (byte)(byte0 | v0);
            //    data[i + 1] = (byte)(byte1 | v1);
            //    data[i + 2] = (byte)(byte2 | v2);
            //    data[i + 3] = (byte)(byte3 | v3);
            //}

            FileStream fs = new FileStream("rom.bin", FileMode.Create, FileAccess.Write);
            fs.Write(data, 0, totalM * 1024 * 1024);
            fs.Close();
            MessageBox.Show("rom.bin ok");

        }

        private void button9_Click(object sender, EventArgs e)
        {
            int totalM = int.Parse(this.textBox3.Text);
            
            mainForm.clearBuff();
            byte[] buff = new byte[totalM * 1024 * 1024];

            FileStream fs = new FileStream("rom.bin", FileMode.Open, FileAccess.Read);
            fs.Read(buff, 0, totalM * 1024 * 1024);
            fs.Close();


            mainForm.clearBuff();
            int err = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < totalM * 256; i++)
            {
                //byte[] data =  readSector(i);
                byte[] data = this.readSectorMem(i);

                for (int j = 0; j < 4096; j++)
                {
                    if (buff[i * 4096 + j] != data[j])
                    {
                        err++;
                        sb.AppendLine(Util.getHex8(i * 4096 + j) + "," + Util.getHex2(buff[i * 4096 + j]) + "," + Util.getHex2(data[j]));
                        if (err >= 64)
                        {
                            textBox1.Text = "err"+sb.ToString()+"\r\n";
                            return;
                        }
                    }
                }
                this.Text = i + "/" + (totalM * 256);
            }

            textBox1.Text = err + ",\r\n";

        }
        




        public uint CH375_DAT = 0x5A000000;
        public uint CH375_DAT4 = 0x5A000004;
        public uint CH375_A0 = 0x5A000004;
        public uint CH375_CS = 0x5A000008;
        public uint CH375_RD = 0x5A00000C;
        public uint CH375_WR = 0x5A000010;

        public uint CMD = 0x01;//01H GET_IC_VER 版本号 获取芯片及固件版本
        public uint DATA = 0x00;//01H GET_IC_VER 版本号 获取芯片及固件版本

        public int GET_IC_VER = 0x01;//01H GET_IC_VER 版本号 获取芯片及固件版本
        public int CHECK_EXIST = 0x06;//06H CHECK_EXIST 任意数据 按位取反 测试工作状态
        public int DISK_INIT = 0x51;//51H DISK_INIT 产生中断 初始化USB存储设备
        public int GET_STATUS = 0x22;//22H GET_STATUS 中断状态 获取中断状态并取消请求
        public int TEST_CONNECT = 0x16;//16H TEST_CONNECT （等2uS） 连接状态 检查USB 设备的连接状态
        public int SET_USB_MODE = 0x15;//15H SET_USB_MODE 模式代码 （等20uS） 操作状态 设置USB 工作模式
        public int DISK_SIZE = 0x53;//53H DISK_SIZE 产生中断 获取USB 存储设备的容量
        public int RD_USB_DATA = 0x28;//28H RD_USB_DATA 数据长度 从当前USB中断的 数据流 端点缓冲区读取数据块
        public int DISK_READ = 0x54;//54H DISK_READ LBA 地址 产生中断 从USB存储设备读数据块
        public int DISK_RD_GO = 0x55;//55H DISK_RD_GO 产生中断 继续USB 存储设备的读操作
        public int RESET_ALL = 0x05;//05H RESET_ALL （等40mS） 执行硬件复位


        private void setCMD(int cmd)
        {
            this.mainForm.setmem(CH375_WR, 1);//WR#

            this.mainForm.setmem(CH375_A0, CMD);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_DAT, (byte)cmd);
            this.mainForm.setmem(CH375_WR, 0);//WR#
            this.mainForm.setmem(CH375_WR, 1);//WR#
        }
        private void setDATA(int data)
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_DAT, (byte)data);
            this.mainForm.setmem(CH375_WR, 0);//WR#
            this.mainForm.setmem(CH375_WR, 1);//WR#
        }
        private uint getDATA()
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_RD, 0);//RD#
            uint val = this.mainForm.getmem(CH375_DAT, null);
            this.mainForm.setmem(CH375_RD, 1);//RD#
            return val;
        }
        private uint getDATA4()
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            //this.mainForm.setmem(CH375_RD, 0);//RD#
            uint val = this.mainForm.getmem(CH375_DAT4, null);
            //this.mainForm.setmem(CH375_RD, 1);//RD#
            return val;
        }

        private uint waitForInt()
        {
            while (true)
            {
                uint tmp = this.mainForm.getmem(CH375_DAT, null);
                if ((tmp & 0x100) == 0)
                {
                    break;
                }
            }

            setCMD(GET_STATUS);
            uint val = getDATA();
            return val;
        }

        private void setMode(int mode)
        {
            setCMD(SET_USB_MODE);
            setDATA(mode);
        }

        private void button11_Click(object sender, EventArgs e)
        {
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setCMD(RESET_ALL);

            Thread.Sleep(100);

            setCMD(GET_IC_VER);

            uint val = getDATA();

            setCMD(CHECK_EXIST);
            setDATA(0x55);

            uint val2 = getDATA();


            this.mainForm.setmem(CH375_CS, 1);//CS#

            this.textBox1.Text += Util.getHex8(val) + ", " + Util.getHex8(val2) + "\r\n";
        }


        private void button12_Click(object sender, EventArgs e)
        {
            uint val;
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setMode(5);//建议在没有USB 设备时使用模式5，插入USB 设备后先进入模式7再换到模式6。

            val = waitForInt();
            this.textBox1.Text += Util.getHex8(val) + "\r\n";

            if (val != 0x115)//15H USB_INT_CONNECT 检测到USB设备连接事件
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }

            setMode(7);

            setMode(6);
            val = waitForInt();
            this.textBox1.Text += Util.getHex8(val) + "\r\n";

            if (val != 0x115)//15H USB_INT_CONNECT 检测到USB设备连接事件
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }


            setCMD(DISK_INIT);

            val = waitForInt();


            this.mainForm.setmem(CH375_CS, 1);//CS#
            this.textBox1.Text += Util.getHex8(val) + "\r\n";
        }

        private void button13_Click(object sender, EventArgs e)
        {
            uint val;
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setCMD(DISK_SIZE);

            val = waitForInt();

            setCMD(RD_USB_DATA);

            //前4个字节以高字节在前组成的双字数据是USB 存储设备的总扇区数，
            //后4个字节以高字节在前组成的双字数据是每个扇区的字节数，
            //两个数据相乘的结果就是以字节为单位的USB存储设备的总容量。
            uint val1 = getDATA();
            if ((val1 & 0xFF) != 8)
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }
            uint secCount = 0;
            uint val2 = getDATA();
            secCount |= (val2 & 0xFF) << 24;
            uint val3 = getDATA();
            secCount |= (val3 & 0xFF) << 16;
            uint val4 = getDATA();
            secCount |= (val4 & 0xFF) << 8;
            uint val5 = getDATA();
            secCount |= (val5 & 0xFF);

            uint secSize = 0;
            uint val6 = getDATA();
            secSize |= (val6 & 0xFF) << 24;
            uint val7 = getDATA();
            secSize |= (val7 & 0xFF) << 16;
            uint val8 = getDATA();
            secSize |= (val8 & 0xFF) << 8;
            uint val9 = getDATA();
            secSize |= (val9 & 0xFF);

            this.mainForm.setmem(CH375_CS, 1);//CS#
            this.textBox1.Text += secCount + "," + secSize + "\r\n";

        }

        private uint[] getData(int lba)
        {
            uint val = 0;
            this.mainForm.setmem(CH375_CS, 0);//CS#
            //该命令从USB 存储设备读取数据块。读取数据块以扇区为基本单位，需要两组参数：起始地址和数据长度，
            //起始地址是以4个字节表示的线性扇区号LBA 地址，数据长度是以1个字节表示的扇区数。
            //该命令需要5 个输入数据，依次是LBA 地址的最低字节，LBA地址的较低字节，LBA地址的较高字节，
            //LBA 地址的最高字节，扇区数。该命令可以在容量高达2000GB 的USB 存储设备中任意读取1 至255
            //个扇区的数据。该命令需要与下面的DISK_RD_GO命令配合使用。

            setCMD(DISK_READ);
            setDATA(lba & 0xFF);
            setDATA((lba >> 8) & 0xFF);
            setDATA((lba >> 16) & 0xFF);
            setDATA((lba >> 24) & 0xFF);
            setDATA(1);

            val = waitForInt();

            uint[] data = new uint[128];

            for (int i = 0; i < 8; i++)
            {
                if (i != 0)
                {
                    setCMD(DISK_RD_GO);
                    val = waitForInt();
                }
                setCMD(RD_USB_DATA);
                uint len = getDATA();
                for (int j = 0; j < 16; j++)
                {
                    //uint temp = getDATA();
                    data[i * 16 + j] = 0;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 0;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 8;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 16;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 24;
                }
            }
            setCMD(DISK_RD_GO);
            val = waitForInt();

            this.mainForm.setmem(CH375_CS, 1);//CS#
            return data;
        }
        private uint[] getData4(int lba)
        {
            uint val = 0;
            this.mainForm.setmem(CH375_CS, 0);//CS#
            //该命令从USB 存储设备读取数据块。读取数据块以扇区为基本单位，需要两组参数：起始地址和数据长度，
            //起始地址是以4个字节表示的线性扇区号LBA 地址，数据长度是以1个字节表示的扇区数。
            //该命令需要5 个输入数据，依次是LBA 地址的最低字节，LBA地址的较低字节，LBA地址的较高字节，
            //LBA 地址的最高字节，扇区数。该命令可以在容量高达2000GB 的USB 存储设备中任意读取1 至255
            //个扇区的数据。该命令需要与下面的DISK_RD_GO命令配合使用。

            setCMD(DISK_READ);
            setDATA(lba & 0xFF);
            setDATA((lba >> 8) & 0xFF);
            setDATA((lba >> 16) & 0xFF);
            setDATA((lba >> 24) & 0xFF);
            setDATA(1);

            val = waitForInt();

            uint[] data = new uint[128];

            for (int i = 0; i < 8; i++)
            {
                if (i != 0)
                {
                    setCMD(DISK_RD_GO);
                    val = waitForInt();
                }
                setCMD(RD_USB_DATA);
                uint len = getDATA();
                for (int j = 0; j < 16; j++)
                {
                    uint temp = getDATA4();
                    data[i * 16 + j] = temp;
                }
            }
            setCMD(DISK_RD_GO);
            val = waitForInt();

            this.mainForm.setmem(CH375_CS, 1);//CS#
            return data;
        }
        private void button14_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream("e:\\out.bin", FileMode.Create, FileAccess.Write);
            int lba = 0;
            while (lba < 1)
            {
                uint[] data;
                if (checkBox2.Checked)
                {
                    data = getData4(lba);
                }
                else {
                    data = getData(lba);
                }
                lba++;
                this.Text = lba + "";
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 128; i++)
                {
                    if ((i & 3) == 0)
                    {
                        sb.Append("\r\n");
                    }
                    sb.Append(Util.getHex8(data[i]));
                    sb.Append(" ");
                }

                byte[] bdata = new byte[512];
                for (int i = 0; i < 128; i++)
                {
                    bdata[i * 4 + 0] = (byte)((data[i] >> 0) & 0xFF);
                    bdata[i * 4 + 1] = (byte)((data[i] >> 8) & 0xFF);
                    bdata[i * 4 + 2] = (byte)((data[i] >> 16) & 0xFF);
                    bdata[i * 4 + 3] = (byte)((data[i] >> 24) & 0xFF);
                }
                fs.Write(bdata, 0, 512);
                fs.Flush();
                //this.textBox4.Text = Util.getHex8(val) + "\r\n";
                this.textBox1.Text = sb.ToString();

                Application.DoEvents();
            }
            fs.Close();
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void button15_Click(object sender, EventArgs e)
        {
            spiCSOn();
            spiSend(0xA3);
            spiSend(0x00);
            spiSend(0x00);
            spiSend(0x00);
            spiCSOff();
            //High Performance Mode A3h dummy dummy dummy
        }

        private void button16_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff(); 
            FileStream fs = new FileStream("romdump.bin", FileMode.Create, FileAccess.Write);
            //FileStream fstext = new FileStream("romdump.bin.text", FileMode.Create, FileAccess.Write);
            //StreamWriter sw = new StreamWriter(fstext);
            int total = int.Parse(this.textBox3.Text) * 256;

            for (int i = 0; i < total; i++)
            {
                byte[] data = this.readSector(i);

                fs.Write(data, 0, 4096);
                fs.Flush();

                //StringBuilder sb = new StringBuilder();
                //for (int j = 0; j < 4; j++)
                //{
                //    sb.Append(Util.getHex2(data[j]));
                //    sb.Append(" ");
                //}
                //sb.Append("\r\n");
                //sw.Write(sb);
                //sw.Flush();
                //textBox1.Text = sb.ToString();
                this.Text = i + "";
            }

            fs.Close();
            //fstext.Close();
        }

        private void button17_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();
            uint READ = 1;
            uint WRITE = 0;

            mainForm.setmem(0x54000000 + 4, 1);//cs
            mainForm.setmem(0x54000000 + 0, 0x80 | (0x1F << 1) | READ);//send read time
            uint t0 = mainForm.getmem(0x54000000 + 0, null);
            uint t1 = mainForm.getmem(0x54000000 + 0, null);
            uint t2 = mainForm.getmem(0x54000000 + 0, null);
            uint t3 = mainForm.getmem(0x54000000 + 0, null);
            uint t4 = mainForm.getmem(0x54000000 + 0, null);
            uint t5 = mainForm.getmem(0x54000000 + 0, null);
            uint t6 = mainForm.getmem(0x54000000 + 0, null);

            mainForm.setmem(0x54000000 + 4, 0);//cs

            string v1 = "";
            v1 += Util.getHex2(t0) + ",";
            v1 += Util.getHex2(t1) + ",";
            v1 += Util.getHex2(t2) + ",";
            v1 += Util.getHex2(t3) + ",";
            v1 += Util.getHex2(t4) + ",";
            v1 += Util.getHex2(t5) + ",";
            v1 += Util.getHex2(t6) + ",";
            this.textBox1.Text = v1;
            /*
            spiCSOn();
            spiSend(0x80 +( 0x20<<1 ) + 0);
            spiSend(42);
            //spiSend(0xBF);
            //uint a0 = spiRec();
            //uint a1 = spiRec();
            //uint a2 = spiRec();
            //uint a3 = spiRec();
            //uint a4 = spiRec();
            //uint a5 = spiRec();
            //uint a6 = spiRec();
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0<<1) + 0);
            spiSend(42);
            //spiSend(0xBF);
            //uint a0 = spiRec();
            //uint a1 = spiRec();
            //uint a2 = spiRec();
            //uint a3 = spiRec();
            //uint a4 = spiRec();
            //uint a5 = spiRec();
            //uint a6 = spiRec();
            spiCSOff();
            */
        }

        private void button18_Click(object sender, EventArgs e)
        {
            mainForm.clearBuff();

            spiCSOn();
            spiSend(0x80 + (0x20 <<1) + 1);
            textBox1.Text = " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x00 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x01 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x02 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

        }

    }
}
